# tryLock 上锁逻辑
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
    internalLockLeaseTime = unit.toMillis(leaseTime);

    return evalWriteAsync(getName(), LongCodec.INSTANCE, command,           // KEYS[1] : lock:coupon:uid:2     ARGV[1]: 30000       ARGV[2]  线程ID

            "if (redis.call('exists', KEYS[1]) == 0) then " +               // exists lock:coupon:uid:2
                    "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +        // hincrby lock:coupon:uid:2  bb37-7872-8734-8834-7787:110 1
                    "redis.call('pexpire', KEYS[1], ARGV[1]); " +           // pexpire lock:coupon:uid:2 30000
                    "return nil; " +
                    "end; " +

            "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +     // hexists lock:coupon:uid:2 bb37-7872-8734-8834-7787:110
                    "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +        // hincrby lock:coupon:uid:2 bb37-7872-8734-8834-7787:110 1
                    "redis.call('pexpire', KEYS[1], ARGV[1]); " +           // pexpire lock:coupon:uid:2 30000
                    "return nil; " +
                    "end; " +

            "return redis.call('pttl', KEYS[1]);",

            Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));
}


# unlock 释放锁逻辑
protected RFuture<Boolean> unlockInnerAsync(long threadId) {
    return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
            "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +    // hexists lock:coupon:uid:2  bb37-7872-8734-8834-7787:110
                    "return nil;" +
                    "end; " +

                "local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +   // hincrby lock:coupon:uid:2 bb37-7872-8734-8834-7787:110 -1
                "if (counter > 0) then " +
                "redis.call('pexpire', KEYS[1], ARGV[2]); " +              // pexpire lock:coupon:uid:2 30000
                "return 0; " +

                "else " +

                "redis.call('del', KEYS[1]); " +           // del lock:coupon:uid:2
                "redis.call('publish', KEYS[2], ARGV[1]); " +
                "return 1; " +
              "end; " +
              "return nil;",
            Arrays.asList(getName(), getChannelName()), LockPubSub.UNLOCK_MESSAGE, internalLockLeaseTime, getLockName(threadId));
}